Hint = "(0,0).s (0,0).t, (m,n).s, (m,n).t, when tex placement is rectangular." $0D "Set these numbers to enforce a rectangular texture scale." $0D "If this is blank, the scale is not rectangular"
}
Corner1: =
{
Txt = "(0,0)" Typ = "EF002"
Hint = "s t texture coordinates for 0,0 corner"
}
Corner2: =
{
Txt = "(0,n)" Typ = "EF002"
Hint = "s t texture coordinates for 0,n corner"
}
Corner3: =
{
Txt = "(m,0)" Typ = "EF002"
Hint = "s t texture coordinates for m,0 corner"
}
Corner4: =
{
Txt = "(m,n)" Typ = "EF002"
Hint = "s t texture coordinates for m,n corner"
}
sep: = { Typ="S" Txt=""}
fixed: ={Txt="fixed int." Typ="X"
}
sep: = { Typ="S" Txt=""}
exit:py = { Txt="" }
}
"""
class CPTexPos(dlgclasses.LiveEditDlg):
endcolor = AQUA
size = (100,100)
dfsep = 0.5
dlgdef = """
{
Style = "9"
Caption = "Positioning Dialog"
Coords: =
{
Txt = "&"
Typ = "EF002"
Hint = "s t texture coordinates. Enter new ones here." $0D "The difference between new and old can be propagated to row, column or all with checkboxes below."
}
sep: = {Typ="S" Txt=" "}
moverow: ={Txt="move row" Typ="X"
Hint = "If this is checked, texture movement applies to whole row (same color)."}
movecol: ={Txt="move col" Typ="X"
Hint = "If this is checked, texture movement applies to whole column (different colors)."}
moveall: ={Txt="move all" Typ="X"
Hint = "If this is checked, whole texture is shifted"}
sep: = { Typ="S" Txt=""}
exit:py = {Txt="" }
}
"""
def pointsToMove(moverow, movecol, i, j, h, w):
"returns list of (i,j) indexes of points to move"
"if moverow==1 and movecol==1, move everything"
if moverow and movecol:
def row(i,w=w):
return map(lambda j,i=i:(i,j),range(w))
return reduce(lambda x,y:x+y, map(row,range(h)))
if movecol:
return map(lambda i,j=j:(i, j),range(h))
if moverow:
return map(lambda j,i=i:(i, j), range(w))
return (i, j), # Newbie Pythonistas: the comma is not a typo,
# but means that the function returns a
# 1-element tuple whose sole element is a 2-tuple.
# The idea here is to use the bezier formulas (see comments to bezier.pas)
# to compute the 1/4, 1/2, 3/4 points on the bezier curve segment
# whose midpoint is at i (in each column), the 1/2 point becomes
# the new even coordinate cp, & the new odd coordinate cp's are
# chosen to get the line to pass thru the 1/4 and 3/4 points.
#
# The structure of this code should be revamped to operate on
# ranges of rows, columns or both at once, then thinning should
# be added.
#
def quilt_addrow(cp,(i,j)):
"alters cp so that two patch-rows replace the ith one"
md, q1, q3 = [], [], []
#
# Should try to do this with maplist ...
#
# & We'll probably want a variant to do this to a whole list
#
for c in range(len(cp[0])):
arc = cp[i-1][c],cp[i][c],cp[i+1][c]
mid = apply(b2midpoint, arc)
md.append(mid)
qt1 = apply(b2qtpoint, arc)
qt3 = apply(b2qt3point, arc)
q1.append(b2midcp(cp[i-1][c],qt1, mid))
q3.append(b2midcp(mid,qt3,cp[i+1][c]))
cp[i:i+1] = [q1, md, q3]
def doubleRowsOfQuilt(cp):
newcp = copyCp(cp)
for i in range(len(cp)-2,0,-2):
quilt_addrow(newcp,(i,0))
return newcp
def quilt_addcol(cp,(i,j)):
"alters cp so that two patch-rows replace the ith one"
for row in cp:
arc = row[j-1],row[j],row[j+1]
mid = apply(b2midpoint, arc)
qt1 = apply(b2qtpoint, arc)
qt3 = apply(b2qt3point, arc)
row[j:j+1]=[b2midcp(arc[0],qt1, mid),
mid,b2midcp(mid,qt3,arc[2])]
def doubleColsOfQuilt(cp):
newcp = copyCp(cp)
for j in range(len(cp[0])-2,0,-2):
quilt_addcol(newcp,(0,j))
return newcp
def quilt_delrow(cp,(i,j)):
md = []
for c in range(len(cp[0])):
arc = cp[i-2][c],cp[i][c],cp[i+2][c]
mid = apply(b2midcp,arc)
md.append(mid)
cp[i-1:i+2]=[md]
def quilt_delcol(cp, (i,j)):
for row in cp:
arc=row[j-2],row[j],row[j+2]
mid = apply(b2midcp,arc)
row[j-1:j+2]=[mid]
#
# Handles for control points.
#
class CPHandle(qhandles.GenericHandle):
"Bezier Control point."
undomsg = Strings[627]
hint = "reshape bezier patch (Ctrl key: force control point to grid)\n Alt: move whole row (same hue)\n Shift: move whole column.\n Shift+Alt key: move everything. \n S: shift texture instead.||This is one of the control points of the selected Bezier patch. Moving this control points allows you to distort the shape of the patch. Control points can be seen as 'attractors' for the 'sheet of paper' Bezier patch."
pickItem = qmenu.item("Pick CP", pickClick,"|When one or more CPs are picked `picked', dragging one of them drags all, and movement palette operations applied to a patch are applied only to the picked CPs.\n\nPatches remember which of their CPs are picked.")
hint = "re-position texture vertexes (Ctrl key: force control point to grid)\n Alt: move whole row (same hue)\n Shift: move whole column.\n Shift+Alt key: move everything. \n S: shift texture instead.||This is one of the control points of the selected Bezier patch. Moving this control points allows you to distort the shape of the patch. Control points can be seen as 'attractors' for the 'sheet of paper' Bezier patch."
def __init__(self, pos, b2, ij, color): #DECKER
qhandles.GenericHandle.__init__(self, pos)
self.b2 = b2
self.ij = ij
self.hint = "(%s,%s)--"%ij+self.hint
self.color = color #DECKER
self.cursor = CR_CROSSH
self.h = len(b2.cp)
self.w = len(b2.cp[0])
def draw(self, view, cv, draghandle=None):
if self.ij == (0,0):
cv.reset()
#self.drawcpnet(view, cv)
p = view.proj(self.pos)
if p.visible:
cv.reset()
cv.brushcolor = self.color #DECKER
cv.rectangle(p.x-3, p.y-3, p.x+4, p.y+4)
#
# This is important because in general the derivative
projtex = qmenu.item("&Project from tagged", projtexclick, "|Texture of a tagged face is projected onto the patch in a `flat' way (just like project texture from tagged face onto faces).")
tagged = gettaggedface(editor)
if tagged is None:
projtex.state=qmenu.disabled
else:
projtex.tagged = tagged
def rotclick(m, o=o, editor=editor):
ncp = RotateCpCounter(1,o.cp)
new = o.copy()
new.cp = ncp
undo=quarkx.action()
undo.exchange(o, new)
editor.ok(undo,"Spin")
editor.invalidateviews()
rotate = qmenu.item("Rotate",rotclick,"|`Rotates' control points without changeing patch shape\n(I'm not sure if it's useful on its own but it helps in the implementation of some things so here it is anyway.)")
def unwarpclick(m,o=o,editor=editor):
new=o.copy()
new.cp = undistortColumns(undistortRows(o.cp))
undo=quarkx.action()
undo.exchange(o, new)
editor.ok(undo,"unwarp")
unwarp = qmenu.item("Unwarp", unwarpclick, "|Tries to reduce texture scale changes within patch, keeping corner points the same.")
def cornertexclick(m,o=o,editor=editor):
class pack:
"a place to stick stuff"
pack.o=o
pack.fixed=""
def reset(self, pack=pack):
cp = pack.o.cp
m = len(cp)-1
n = len(cp[0])-1
one = cp[0][0].s, cp[0][0].t, cp[m][n].s, cp[m][n].t
two = cp[m][0].s, cp[0][n].t, cp[0][n].s ,cp[m][0].t
cornertex = qmenu.item("Position by &corners",cornertexclick,"|A dialog for positioning textures by specifying the texture coordinates of the corners of the patch")